package com.alibaba.cloud.ddd.domain.model.cargo;

import java.util.Date;

import com.alibaba.cloud.ddd.domain.model.location.Location;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import com.alibaba.cloud.ddd.domain.model.voyage.Voyage;
import com.alibaba.cloud.ddd.domain.shared.ValueObject;

/**
 * An itinerary consists of one or more legs.
 */
@Entity(name = "Leg")
@Table(name = "Leg")
public class Leg implements ValueObject<Leg> {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6810255651864531687L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	public long id;

	@ManyToOne
	@JoinColumn(name = "voyage_id")
	public Voyage voyage;

	@ManyToOne
	@JoinColumn(name = "load_location_id")
	public Location loadLocation;

	@Column(name = "load_time")
	public Date loadTime;

	@ManyToOne
	@JoinColumn(name = "unload_location_id")
	public Location unloadLocation;

	@Column(name = "unload_time")
	public Date unloadTime;

	public Leg(Voyage voyage, Location loadLocation, Location unloadLocation, Date loadTime, Date unloadTime) {
		Validate.noNullElements(new Object[] { voyage, loadLocation, unloadLocation, loadTime, unloadTime });

		this.voyage = voyage;
		this.loadLocation = loadLocation;
		this.unloadLocation = unloadLocation;
		this.loadTime = loadTime;
		this.unloadTime = unloadTime;
	}

	public Voyage voyage() {
		return voyage;
	}

	public Location loadLocation() {
		return loadLocation;
	}

	public Location unloadLocation() {
		return unloadLocation;
	}

	public Date loadTime() {
		return new Date(loadTime.getTime());
	}

	public Date unloadTime() {
		return new Date(unloadTime.getTime());
	}

	@Override
	public boolean sameValueAs(final Leg other) {
		return other != null && new EqualsBuilder().append(this.voyage, other.voyage)
				.append(this.loadLocation, other.loadLocation).append(this.unloadLocation, other.unloadLocation)
				.append(this.loadTime, other.loadTime).append(this.unloadTime, other.unloadTime).isEquals();
	}

	@Override
	public boolean equals(final Object o) {
		if (this == o)
			return true;
		if (o == null || getClass() != o.getClass())
			return false;

		Leg leg = (Leg) o;

		return sameValueAs(leg);
	}

	@Override
	public int hashCode() {
		return new HashCodeBuilder().append(voyage).append(loadLocation).append(unloadLocation).append(loadTime)
				.append(unloadTime).toHashCode();
	}

	Leg() {
		// Needed by Hibernate
	}
}
